{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Tutorial How-To\n",
    "\n",
    "This tutorial requires this initial notebook to be run first so that the requirements and environment variables are stored for all notebooks in the workshop."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## How to get started\n",
    "\n",
    "1. If you are attending an instructor lead workshop or deployed the workshop infrastructure using the provided [CloudFormation Template](https://raw.githubusercontent.com/aws-samples/prompt-engineering-with-anthropic-claude-v-3/main/cloudformation/workshop-v1-final-cfn.yml) you can proceed to step 2, otherwise you will need to download the workshop [GitHub Repository](https://github.com/aws-samples/prompt-engineering-with-anthropic-claude-v-3) to your local machine.\n",
    "\n",
    "2. Install the required dependencies by running the following command:\n",
    " "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "> ⚠️ **Please ignore error messages related to pip's dependency resolver.**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "%pip install -qU pip\n",
    "%pip install -qUr requirements.txt --force-reinstall"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "3. Run the notebook cells in order, following the instructions provided."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "---\n",
    "\n",
    "## Usage Notes & Tips 💡\n",
    "\n",
    "- This course uses Claude 3 Haiku with temperature 0. We will talk more about temperature later in the course. For now, it's enough to understand that these settings yield more deterministic results. All prompt engineering techniques in this course also apply to previous generation legacy Claude models such as Claude 2 and Claude Instant 1.2.\n",
    "\n",
    "- You can use `Shift + Enter` to execute the cell and move to the next one.\n",
    "\n",
    "- When you reach the bottom of a tutorial page, navigate to the next numbered file in the folder, or to the next numbered folder if you're finished with the content within that chapter file.\n",
    "\n",
    "### The Boto3 SDK & the Converse API\n",
    "We will be using the [Amazon Boto3 SDK](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/bedrock-runtime.html) and the [Converse API](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/bedrock-runtime/client/converse.html) throughout this tutorial. \n",
    "\n",
    "Below is an example of what running a prompt will look like in this tutorial. First, we create `get_completion`, which is a helper function that sends a prompt to Claude and returns Claude's generated response. Run that cell now."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "First, we set and store the model name and region."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import boto3\n",
    "import json\n",
    "from datetime import datetime\n",
    "from botocore.exceptions import ClientError\n",
    "\n",
    "session = boto3.Session()\n",
    "region = session.region_name"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "#modelId = 'anthropic.claude-3-sonnet-20240229-v1:0'\n",
    "modelId = 'anthropic.claude-3-haiku-20240307-v1:0'\n",
    "\n",
    "%store modelId\n",
    "%store region\n",
    "\n",
    "print(f'Using modelId: {modelId}')\n",
    "print('Using region: ', region)\n",
    "\n",
    "bedrock_client = boto3.client(service_name = 'bedrock-runtime', region_name = region,)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Then, we create `get_completion`, which is a helper function that sends a prompt to Claude and returns Claude's generated response. Run that cell now."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "def get_completion(prompt, system_prompt=None):\n",
    "    # Define the inference configuration\n",
    "    inference_config = {\n",
    "        \"temperature\": 0.0,  # Set the temperature for generating diverse responses\n",
    "        \"maxTokens\": 200  # Set the maximum number of tokens to generate\n",
    "    }\n",
    "    # Define additional model fields\n",
    "    additional_model_fields = {\n",
    "        \"top_p\": 1,  # Set the top_p value for nucleus sampling\n",
    "    }\n",
    "    # Create the converse method parameters\n",
    "    converse_api_params = {\n",
    "        \"modelId\": modelId,  # Specify the model ID to use\n",
    "        \"messages\": [{\"role\": \"user\", \"content\": [{\"text\": prompt}]}],  # Provide the user's prompt\n",
    "        \"inferenceConfig\": inference_config,  # Pass the inference configuration\n",
    "        \"additionalModelRequestFields\": additional_model_fields  # Pass additional model fields\n",
    "    }\n",
    "    # Check if system_text is provided\n",
    "    if system_prompt:\n",
    "        # If system_text is provided, add the system parameter to the converse_params dictionary\n",
    "        converse_api_params[\"system\"] = [{\"text\": system_prompt}]\n",
    "\n",
    "    # Send a request to the Bedrock client to generate a response\n",
    "    try:\n",
    "        response = bedrock_client.converse(**converse_api_params)\n",
    "\n",
    "        # Extract the generated text content from the response\n",
    "        text_content = response['output']['message']['content'][0]['text']\n",
    "\n",
    "        # Return the generated text content\n",
    "        return text_content\n",
    "\n",
    "    except ClientError as err:\n",
    "        message = err.response['Error']['Message']\n",
    "        print(f\"A client error occured: {message}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Now we will write out an example prompt for Claude and print Claude's output by running our `get_completion` helper function. Running the cell below will print out a response from Claude beneath it.\n",
    "\n",
    "Feel free to play around with the prompt string to elicit different responses from Claude."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "# Prompt\n",
    "prompt = \"Hello, Claude!\"\n",
    "\n",
    "# Get Claude's response\n",
    "print(get_completion(prompt))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The `modelId` and `region` variables defined earlier will be used throughout the tutorial. Just make sure to run the cells for each tutorial page from top to bottom."
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "conda_tensorflow2_p310",
   "language": "python",
   "name": "conda_tensorflow2_p310"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.14"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
